﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Input;

namespace XNAGuiLib.GuiLibAction
{

    public class KeyAction : Action
    {
        //
        #region Field List - KeyList
        protected List<Keys> _keys = new List<Keys>();
        /// <summary>
        /// gets or sets the Key List for this Action
        /// </summary>
        public List<Keys> KeyList
        {
            get
            {
                return _keys;
            }
            set
            {
                _keys = value;
            }
        }
        #endregion
        //
        #region Field - Input
        protected Inputs _input;
        /// <summary>
        /// gets or sets the input for this KeyAction
        /// </summary>
        public Inputs Input
        {
            get
            {
                return _input;
            }
            set
            {
                _input = value;
            }
        }
        #endregion
        //
        #region Enumeration - Inputs
        public enum Inputs
        {
            /// <summary>
            /// any key of the keyboard hold down
            /// </summary>
            KeyDown,
            /// <summary>
            /// any key of the keyboard hold down and released
            /// </summary>
            KeyPressed,
            /// <summary>
            /// any key of the keyboard released
            /// </summary>
            KeyReleased
        }
        #endregion
        //
        //
        #region Constructor - KeyAction()
        public KeyAction()
        { }
        #endregion
        //
        //
        // check for the CommandType and if the Action's key is pressed (down and released afterwards)
        // executes a command depending on the CommandType
        #region Private Method - CheckKeyPressed()
        private void CheckKeyPressed()
        {
            if (_type == CommandType.Custom && KeysPressed())
            {
                Execute();
            }
            else if (_type == CommandType.ToggleVisibility && KeysPressed())
            {
                ExecuteActionToggleVisibility();
            }
            else if (_type == CommandType.Hide && KeysPressed())
            {
                ExecuteActionHide();
            }
            else if (_type == CommandType.Show && KeysPressed())
            {
                ExecuteActionShow();
            }
            else if (_type == CommandType.MoveUp && KeysPressed())
            {
                ExecuteActionMoveUp();
            }
            else if (_type == CommandType.MoveDown && KeysPressed())
            {
                ExecuteActionMoveDown();
            }
            else if (_type == CommandType.MoveLeft && KeysPressed())
            {
                ExecuteActionMoveLeft();
            }
            else if (_type == CommandType.MoveRight && KeysPressed())
            {
                ExecuteActionMoveRight();
            }

        }
        #endregion
        // check for the CommandType and if the Action's key is down (only down)
        // executes a command depending on the CommandType
        #region Private Method - CheckKeyDown()
        private void CheckKeyDown()
        {
            if (_type == CommandType.Custom && KeysDown())
            {
                Execute();
            }
            else if (_type == CommandType.ToggleVisibility && KeysDown())
            {
                ExecuteActionToggleVisibility();
            }
            else if (_type == CommandType.Hide && KeysDown())
            {
                ExecuteActionHide();
            }
            else if (_type == CommandType.Show && KeysDown())
            {
                ExecuteActionShow();
            }
            else if ((_ms.X != _oms.X || _ms.Y != _oms.Y) && KeysDown())
            {
                if (_type == CommandType.Move && _initialMouseDownInsideInterfaceObject)
                {
                    ExecuteActionMove(_ms, _oms);
                }
            }
            else if (_type == CommandType.MoveUp && KeysDown())
            {
                ExecuteActionMoveUp();
            }
            else if (_type == CommandType.MoveDown && KeysDown())
            {
                ExecuteActionMoveDown();
            }
            else if (_type == CommandType.MoveLeft && KeysDown())
            {
                ExecuteActionMoveLeft();
            }
            else if (_type == CommandType.MoveRight && KeysDown())
            {
                ExecuteActionMoveRight();
            }
        }
        #endregion
        // check for the CommandType and if the Action's key is release (only released) will always execute then the key isn't down
        // executes a command depending on the CommandType
        #region Private Method - CheckKeyReleased()
        private void CheckKeyReleased()
        {
            if (_type == CommandType.Custom && KeysReleased())
            {
                Execute();
            }
            else if (_type == CommandType.ToggleVisibility && KeysReleased())
            {
                ExecuteActionToggleVisibility();
            }
            else if (_type == CommandType.Hide && KeysReleased())
            {
                ExecuteActionHide();
            }
            else if (_type == CommandType.Show && KeysReleased())
            {
                ExecuteActionShow();
            }
            else if ((_ms.X != _oms.X || _ms.Y != _oms.Y) && KeysReleased())
            {
                if (_type == CommandType.Move && _initialMouseDownInsideInterfaceObject)
                {
                    ExecuteActionMove(_ms, _oms);
                }
            }
            else if (_type == CommandType.MoveUp && KeysReleased())
            {
                ExecuteActionMoveUp();
            }
            else if (_type == CommandType.MoveDown && KeysReleased())
            {
                ExecuteActionMoveDown();
            }
            else if (_type == CommandType.MoveLeft && KeysReleased())
            {
                ExecuteActionMoveLeft();
            }
            else if (_type == CommandType.MoveRight && KeysReleased())
            {
                ExecuteActionMoveRight();
            }
        }
        #endregion
        //
        //
        // check if the keys in the action's key list are pressed (down and released)
        #region Private Method - CheckKeysPressed()
        private bool KeysPressed()
        {
            // temporary bool array for each key set to the action
            bool[] tempBool = new bool[_keys.Count];
            // loop for each key in the action's key list
            for (int i = 0; i < _keys.Count; i++)
            {
                // reference the [i]th key from the action's key list
                Keys key = _keys[i];
                // check if the key is up in this update cycle and was down in the last update cycle
                if (_ks.IsKeyUp(key) && _oks.IsKeyDown(key))
                {
                    // set the [i]th bool in the array to true
                    tempBool[i] = true;
                }
                // otherwise set the [i]th bool in the array to false
                else tempBool[i] = false;
            }
            // loop foreach bool in the bool array
            foreach (bool temp in tempBool)
            {
                // if one of the bool in the arrayi is false break the loop and return false
                if (!temp) return false;
            }
            // otherwise return true
            return true;
        }
        #endregion
        //
        // check if the keys in the action's key list are down (down only)
        #region Private Method - CheckKeysDown()
        private bool KeysDown()
        {
            // temporary bool array for each key set to the action
            bool[] tempBool = new bool[_keys.Count];
            // loop for each key in the action's key list
            for (int i = 0; i < _keys.Count; i++)
            {
                // reference the [i]th key from the action's key list
                Keys key = _keys[i];
                // check if the key is down in this update cycle
                if (_ks.IsKeyDown(key))
                {
                    // set the [i]th bool in the array to true
                    tempBool[i] = true;
                }
                // otherwise set the [i]th bool in the array to false
                else tempBool[i] = false;
            }
            // loop foreach bool in the bool array
            foreach (bool temp in tempBool)
            {
                // if one of the bool in the arrayi is false break the loop and return false
                if (!temp) return false;
            }
            // otherwise return true
            return true;
        }
        #endregion
        //
        // check if the keys in the action's key list are released (released only)
        #region Private Method - CheckKeysReleased()
        private bool KeysReleased()
        {
            // temporary bool array for each key set to the action
            bool[] tempBool = new bool[_keys.Count];
            // loop for each key in the action's key list
            for (int i = 0; i < _keys.Count; i++)
            {
                // reference the [i]th key from the action's key list
                Keys key = _keys[i];
                // check if the key is down in this update cycle
                if (_ks.IsKeyUp(key))
                {
                    // set the [i]th bool in the array to true
                    tempBool[i] = true;
                }
                // otherwise set the [i]th bool in the array to false
                else tempBool[i] = false;
            }
            // loop foreach bool in the bool array
            foreach (bool temp in tempBool)
            {
                // if one of the bool in the arrayi is false break the loop and return false
                if (!temp) return false;
            }
            // otherwise return true
            return true;
        }
        #endregion
        //
        //
        // method to check the keyboard input by the type of Inputs where set to this action
        #region Override Method - CheckKeyboard(KeyboardState ks)
        public override void CheckKeyboard(KeyboardState ks)
        {
            _ks = ks;
            // switch on the Inputs set to this action
            switch (_input)
            {
                // case: 'KeyPressed'
                case Inputs.KeyPressed:
                    CheckKeyPressed();
                    break;
                // case: 'KeyDown'
                case Inputs.KeyDown:
                    CheckKeyDown();
                    break;
                // case: 'KeyReleased'
                case Inputs.KeyReleased:
                    CheckKeyReleased();
                    break;
            }
            // set the current keyboardstate to the old keyboardstate
            _oks = _ks;
        }
        #endregion
        // method to check the mouse input
        #region Override Method - CheckMouseButton(MouseState ms)
        public override void CheckMouseButton(MouseState ms)
        {
            // empty, no reason to implement mouse input on KeyAction
        }
        #endregion
    }
}